? config.php ? dbpatch.txt ? newpatch.txt ? patch-extra.txt ? patch.txt ? blog/backuplib.php ? lib/db/.install.xml.swp ? mod/assignment/type/blog Index: admin/settings/security.php =================================================================== RCS file: /cvsroot/moodle/moodle/admin/settings/security.php,v retrieving revision 1.29 diff -u -a -w -b -B -r1.29 security.php --- admin/settings/security.php 22 Jul 2008 04:07:59 -0000 1.29 +++ admin/settings/security.php 13 Aug 2008 04:16:14 -0000 @@ -46,6 +46,7 @@ 1 => get_string('personalblogs','blog'), 0 => get_string('disableblogs','blog')))); $temp->add(new admin_setting_configcheckbox('usetags', get_string('usetags','admin'),get_string('configusetags', 'admin'),'1')); + $temp->add(new admin_setting_configcheckbox('useassoc', get_string('useassoc','admin'),get_string('configuseassoc', 'admin'),'1')); $temp->add(new admin_setting_configcheckbox('keeptagnamecase', get_string('keeptagnamecase','admin'),get_string('configkeeptagnamecase', 'admin'),'1')); $temp->add(new admin_setting_configcheckbox('cronclionly', get_string('cronclionly', 'admin'), get_string('configcronclionly', 'admin'), 0)); $temp->add(new admin_setting_configpasswordunmask('cronremotepassword', get_string('cronremotepassword', 'admin'), get_string('configcronremotepassword', 'admin'), '')); Index: blocks/blog_menu/block_blog_menu.php =================================================================== RCS file: /cvsroot/moodle/moodle/blocks/blog_menu/block_blog_menu.php,v retrieving revision 1.18 diff -u -a -w -b -B -r1.18 block_blog_menu.php --- blocks/blog_menu/block_blog_menu.php 2 May 2008 04:37:04 -0000 1.18 +++ blocks/blog_menu/block_blog_menu.php 13 Aug 2008 04:16:15 -0000 @@ -1,6 +1,7 @@ dirroot .'/blog/lib.php'); +require_once($CFG->dirroot .'/course/lib.php'); class block_blog_menu extends block_base { @@ -11,7 +12,7 @@ } function get_content() { - global $CFG, $USER, $COURSE; + global $CFG, $USER, $COURSE, $DB, $PAGE; if (empty($CFG->bloglevel)) { $this->content->text = ''; @@ -39,22 +40,54 @@ $this->content = new stdClass; $this->content->footer = ''; - if (empty($this->instance) /*|| empty($CFG->blog_version)*/) { + if (empty($this->instance)) { // Either we're being asked for content without // an associated instance of the Blog module has never been installed. $this->content->text = $output; return $this->content; } - //if ( blog_isLoggedIn() && !isguest() ) { - $courseviewlink = ''; + //discover context for pre-loaded associations + $basefilters = array(); + if(!empty($COURSE)) $courseid = $COURSE->id; + switch($PAGE->get_type()) { + case PAGE_COURSE_VIEW: + $courseid = $PAGE->courserecord->id; + $basefilters['courseid'] = $courseid; + break; + case PAGE_BLOG_VIEW: + $basefilters = $PAGE->filters; + if(!empty($PAGE->filters['course'])) + $courseid = $PAGE->filters['course']; + if(!empty($PAGE->filters['mod'])) + $modid = $PAGE->filters['mod']; + if(!empty($PAGE->filters['user'])) + $userid = $PAGE->filters['user']; + if(!empty($PAGE->filters['group'])) + $groupid = $PAGE->filters['group']; + if(!empty($PAGE->filters['tag'])) + $tagid = $PAGE->filters['tag']; + break; + } + $addentrylink = ''; - $coursearg = ''; + $blogprefslink = ''; + $myviewlink = ''; + $siteviewlink = ''; + $courseviewlink = ''; + $modviewlink = ''; + $groupviewlink = ''; + $userviewlink = ''; + $tagviewlink = ''; + $coursepopuplink = ''; + $modpopuplink = ''; + $grouppopuplink = ''; + $userspopuplink = ''; + //create basic blog preference links + $coursearg = ''; $sitecontext = get_context_instance(CONTEXT_SYSTEM); - - if ($COURSE->id != SITEID) { - + if ($courseid != SITEID) { $incoursecontext = true; $curcontext = get_context_instance(CONTEXT_COURSE, $COURSE->id); } else { @@ -61,23 +94,13 @@ $incoursecontext = false; $curcontext = $sitecontext; } - $canviewblogs = has_capability('moodle/blog:view', $curcontext); - - /// Accessibility: markup as a list. - if ( (isloggedin() && !isguest()) && $incoursecontext && $CFG->bloglevel >= BLOG_COURSE_LEVEL && $canviewblogs) { - - $coursearg = '&courseid='.$COURSE->id; - // a course is specified - - $courseviewlink = '
  • '; - $courseviewlink .= get_string('viewcourseentries', 'blog') ."
  • \n"; + $coursearg = '&courseid='.$courseid; + if(!empty($modid)) $coursearg .= '&modid='.$modid; } - $blogmodon = false; - if ( (isloggedin() && !isguest()) && (!$blogmodon || ($blogmodon && $coursearg != '')) && $CFG->bloglevel >= BLOG_USER_LEVEL ) { @@ -81,42 +104,142 @@ if ( (isloggedin() && !isguest()) && (!$blogmodon || ($blogmodon && $coursearg != '')) && $CFG->bloglevel >= BLOG_USER_LEVEL ) { - - // show Add entry link + // create the Add entry link if (has_capability('moodle/blog:create', $sitecontext)) { $addentrylink = '
  • '.get_string('addnewentry', 'blog') ."
  • \n"; } - // show View my entries link - $addentrylink .= '
  • '.get_string('viewmyentries', 'blog'). - "
  • \n"; - - // show link to manage blog prefs - $addentrylink .= '
  • wwwroot. '/blog/preferences.php?userid='. $userBlog->userid . $coursearg .'">'. get_string('blogpreferences', 'blog')."
  • \n"; - - $output = $addentrylink; - $output .= $courseviewlink; + // create the View my entries link + $myviewlink = '
  • '. + //''.fullname($USER). + get_string('viewmyentries', 'blog'). + "
  • \n"; } - // show View site entries link + // create the View site entries link if ($CFG->bloglevel >= BLOG_SITE_LEVEL && $canviewblogs) { - $output .= '
  • '; - $output .= get_string('viewsiteentries', 'blog')."
  • \n"; + $siteviewlink .= '
  • '. + get_string('viewsiteentries', 'blog'). + //$DB->get_field('course', 'shortname', array('format'=>'site')). + "
  • \n"; } - // took out tag management interface/link, should use tag/manage.php + //create 'view blogs for course' link + if($incoursecontext and (!empty($modid) or !empty($userid) or !empty($tagid) or !empty($groupid) or + $PAGE->get_type() == PAGE_COURSE_VIEW) + and $CFG->bloglevel >= BLOG_COURSE_LEVEL and $canviewblogs) { + $courseviewlink = '
  • ' + .''. + $DB->get_field('course', 'shortname', array('id'=>$courseid)) ."
  • \n"; + } + + //create 'view blogs for user' link + if(!empty($userid) and $userid != $USER->id and (!empty($modid) or !empty($courseid) or !empty($tagid) or !empty($groupid)) + and $canviewblogs) { + $userviewlink = '
  • '. + ''. + $DB->get_field('user', 'username', array('id'=>$userid)). + "
  • \n"; + } + + //create 'view blogs for mod' link + if(!empty($modid) and (!empty($groupid) or !empty($userid) or !empty($tagid)) + and $CFG->bloglevel >= BLOG_COURSE_LEVEL and $canviewblogs) { + $filtercontext = get_context_instance(CONTEXT_MODULE, $modid); + $modinfo = $DB->get_record('course_modules', array('id' => $filtercontext->instanceid)); + $modname = $DB->get_field('modules', 'name', array('id' => $modinfo->module)); + $modviewlink = '
  • '. + ''. + $DB->get_field($modname, 'name', array('id' => $modinfo->instance)). + "
  • \n"; + } - // show Help with blogging link - //$output .= '
  • '; - //$output .= get_string('helpblogging', 'blog') ."
  • \n"; - //} else { - // $output = ''; //guest users and users who are not logged in do not get menus - //} + //create 'view blogs for group' link + if(!empty($groupid) and (!empty($modid) or !empty($tagid) or !empty($userid)) + and $CFG->bloglevel >= BLOG_GROUP_LEVEL and $canviewblogs) { + $groupviewlink = '
  • '. + ''. + $DB->get_field('groups', 'name', array('id'=>$groupid)) ."
  • \n"; + } + + //create 'view blogs for tag' link + if(!empty($tagid) && (!empty($modid) or !empty($userid) or !empty($courseid) or !empty($groupid)) and $canviewblogs) { + $tagviewlink = '
  • '.get_string('tag', 'tag').': '. + $DB->get_field('tag', 'name', array('id'=>$tagid))."
  • \n"; + } + + //create 'view blogs for this site's courses' link + if(!$incoursecontext and $canviewblogs and $CFG->bloglevel >= BLOG_GROUP_LEVEL) { + $courseoptions = array(0 => 'none'); + foreach($DB->get_records('course', array()) as $course) { + if($course->id != SITEID) + $courseoptions['courseid='.$course->id] = $course->shortname; + } + $coursepopuplink = '
  • '.popup_form(blog_get_blogs_url($basefilters), + $courseoptions, 'view_course_blogs', '', + get_string('course'), + '', '', true)."
  • \n"; + } + + //create 'view blogs for this course's mods' link + if(!empty($courseid) and $canviewblogs and $CFG->bloglevel >= BLOG_GROUP_LEVEL) { + $mods = array(0 => 'none'); + $modnames = array(); + $modnamesplural = array(); + $modnamesused = array(); + $modoptions = array(); + get_all_mods($courseid, $mods, $modnames, $modnamesplural, $modnamesused); + foreach($mods as $i => $mod) { + $modoptions['modid='.$mod->id] = $DB->get_field($mod->modname, 'name', array('id' => $mod->instance)); + } + $modpopuplink = '
  • '.popup_form(blog_get_blogs_url($basefilters), + $modoptions, 'view_mod_blogs', '', + get_string('resource').'/'.get_string('activity'), + '', '', true)."
  • \n"; + } + + //create 'view blogs for this course's groups link + if($incoursecontext and $canviewblogs and $CFG->bloglevel >= BLOG_GROUP_LEVEL) { + $groupoptions = array(0 => 'none'); + foreach($DB->get_records('groups', array('courseid'=>$courseid)) as $group) { + $groupoptions['groupid='.$group->id] = $group->name; + } + $grouppopuplink = '
  • '.popup_form(blog_get_blogs_url($basefilters), + $groupoptions, 'view_group_blogs', '', + get_string('group'), + '', '', true)."
  • \n"; + } + + //create 'view blogs for this group's users link + if(!empty($groupid) and $canviewblogs and $CFG->bloglevel >= BLOG_GROUP_LEVEL) { + $useroptions = array(0 => 'none'); + foreach($DB->get_records('groups_members', array('groupid'=>$groupid)) as $member) { + $useroptions['userid='.$member->userid] = $DB->get_field('user', 'username', array('id'=>$member->userid)); + } + $userspopuplink = '
  • '.popup_form(blog_get_blogs_url($basefilters), + $useroptions, 'view_user_blogs', '', + get_string('user'), + '', '', true)."
  • \n"; + + } + + + $this->content->text = + '\n"; - $this->content->text = '\n"; return $this->content; } } Index: blocks/blog_tags/block_blog_tags.php =================================================================== RCS file: /cvsroot/moodle/moodle/blocks/blog_tags/block_blog_tags.php,v retrieving revision 1.38 diff -u -a -w -b -B -r1.38 block_blog_tags.php --- blocks/blog_tags/block_blog_tags.php 17 Jul 2008 04:22:41 -0000 1.38 +++ blocks/blog_tags/block_blog_tags.php 13 Aug 2008 04:16:15 -0000 @@ -158,7 +158,7 @@ break; } - $link = $CFG->wwwroot.'/blog/index.php?filtertype='.$filtertype.'&filterselect='.$filterselect.'&tagid='.$tag->id; + $link = blog_get_blogs_url(array($filtertype => $filterselect, 'tag'=>$tag->id)); $this->content->text .= '
  • '. Index: blog/blogpage.php =================================================================== RCS file: /cvsroot/moodle/moodle/blog/blogpage.php,v retrieving revision 1.17 diff -u -a -w -b -B -r1.17 blogpage.php --- blog/blogpage.php 27 Jun 2008 03:35:22 -0000 1.17 +++ blog/blogpage.php 13 Aug 2008 04:16:15 -0000 @@ -15,8 +15,7 @@ var $editing = false; var $courserecord = NULL; var $courseid = NULL; - var $filtertype = NULL; - var $filterselect = NULL; + var $filters = array(); var $tagid = NULL; // Mandatory; should return our identifier. @@ -59,7 +58,7 @@ } // I need to determine how best to utilize this function. Most init // is already done before we get here in blogFilter and blogInfo - + if(!empty($this->filters['course'])) $this->courseid = $this->filters['course']; if ($this->courseid == 0 || $this->courseid == 1 || !is_numeric($this->courseid) ) { $this->courseid = ''; $courserecord = NULL; @@ -118,17 +117,26 @@ return $array; } - if (!empty($this->courseid)) { - $array['courseid'] = $this->courseid; + if(!empty($this->filters['course'])) { + $array['courseid'] = $this->filters['course']; + } + if(!empty($this->filters['mod'])) { + $array['modid'] = $this->filters['mod']; + } + if(!empty($this->filters['group'])) { + $array['groupid'] = $this->filters['group']; + } + if(!empty($this->filters['user'])) { + $array['userid'] = $this->filters['user']; } - if (!empty($this->filtertype)) { - $array['filtertype'] = $this->filtertype; + if(!empty($this->filters['post'])) { + $array['postid'] = $this->filters['post']; } - if (!empty($this->filterselect)) { - $array['filterselect'] = $this->filterselect; + if(!empty($this->filters['tag'])) { + $array['tagid'] = $this->filters['tag']; } - if (!empty($this->tagid)) { - $array['tagid'] = $this->tagid; + if(!empty($this->filters['tagtext'])) { + $array['tag'] = $this->filters['tagtext']; } return $array; } Index: blog/edit.php =================================================================== RCS file: /cvsroot/moodle/moodle/blog/edit.php,v retrieving revision 1.68 diff -u -a -w -b -B -r1.68 edit.php --- blog/edit.php 31 Jul 2008 22:15:31 -0000 1.68 +++ blog/edit.php 13 Aug 2008 04:16:15 -0000 @@ -7,6 +7,7 @@ $action = required_param('action', PARAM_ALPHA); $id = optional_param('id', 0, PARAM_INT); $confirm = optional_param('confirm', 0, PARAM_BOOL); +$modid = optional_param('modid', 0, PARAM_INT); $courseid = optional_param('courseid', 0, PARAM_INT); // needed for user tab - does nothing here require_login($courseid); @@ -70,7 +71,39 @@ } require_once('edit_form.php'); -$blogeditform = new blog_edit_form(null, compact('existing', 'sitecontext')); +if(!empty($existing)) { + $assignmentdata = $DB->get_record_sql('SELECT a.timedue, a.preventlate, a.emailteachers, a.var2, asub.grade + FROM {assignment} a, {assignment_submissions} as asub WHERE + a.id = asub.assignment AND userid = '.$USER->id.' AND a.assignmenttype = \'blog\' + AND asub.data1 = \''.$existing->id.'\''); +} +//add associations +if(!empty($existing)) { + if ($blogassociations = $DB->get_records('blog_association', array('blogid' => $existing->id))) { + foreach($blogassociations as $assocrec) { + $contextrec = $DB->get_record('context', array('id' => $assocrec->contextid)); + switch($contextrec->contextlevel) { + case CONTEXT_COURSE: + $existing->courseassoc = $assocrec->contextid; + break; + case CONTEXT_MODULE: + $existing->modassoc[] = $assocrec->contextid; + break; + } + } + } +} + +if($action == 'add' and $courseid) { //pre-select the course for associations + $context = get_context_instance(CONTEXT_COURSE, $courseid); + $existing->courseassoc = $context->id; +} +if($action == 'add' and $modid) { //pre-select the mod for associations + $context = get_context_instance(CONTEXT_MODULE, $modid); + $existing->modassoc = array($context->id); +} + +$blogeditform = new blog_edit_form(null, compact('existing', 'sitecontext', 'assignmentdata')); if ($blogeditform->is_cancelled()){ redirect($returnurl); @@ -101,6 +134,14 @@ $post->publishstate = 'site'; $strformheading = get_string('addnewentry', 'blog'); $post->action = $action; + if($courseid) { //pre-select the course for associations + $context = get_context_instance(CONTEXT_COURSE, $courseid); + $post->courseassoc = $context->id; + } + if($modid) { //pre-select the mod for associations + $context = get_context_instance(CONTEXT_MODULE, $modid); + $post->modassoc = array($context->id); + } break; case 'edit': @@ -109,10 +150,16 @@ } $post->id = $existing->id; $post->subject = $existing->subject; + $post->fakesubject = $existing->subject; $post->summary = $existing->summary; + $post->fakesummary = $existing->summary; $post->publishstate = $existing->publishstate; $post->format = $existing->format; $post->action = $action; + if(!empty($existing->courseassoc)) + $post->courseassoc = $existing->courseassoc; + if(!empty($existing->modassoc)) + $post->modassoc = $existing->modassoc; $strformheading = get_string('updateentrywithid', 'blog'); if ($itemptags = tag_get_tags_csv('post', $post->id, TAG_RETURN_TEXT, 'default')) { @@ -138,6 +185,8 @@ $navigation = build_navigation($navlinks); print_header("$SITE->shortname: $strblogs", $SITE->fullname, $navigation,'','',true); + + $blogeditform->set_data($post); $blogeditform->display(); @@ -153,13 +202,25 @@ * Delete blog post from database */ function do_delete($post) { - global $returnurl, $DB; + global $returnurl, $DB, $USER; + + //check to see if it's part of a submitted blog assignment + if($blogassignment = $DB->get_record_sql('SELECT a.timedue, a.preventlate, a.emailteachers, asub.grade + FROM {assignment} a, {assignment_submissions} as asub WHERE + a.id = asub.assignment AND userid = '.$USER->id.' AND a.assignmenttype = \'blog\' + AND asub.data1 = \''.$post->id.'\'')) { + print_error('cantdeleteblogassignment', 'blog', $returnurl); + } blog_delete_attachments($post); $status = $DB->delete_records('post', array('id'=>$post->id)); tag_set('post', $post->id, array()); + blog_delete_old_attachments($post); + + blog_remove_associations_for_post($post->id); + add_to_log(SITEID, 'blog', 'delete', 'index.php?userid='. $post->userid, 'deleted blog entry with entry id# '. $post->id); if (!$status) { @@ -189,6 +250,9 @@ } add_tags_info($post->id); + + if(!empty($CFG->useassoc)) add_associations($post); + add_to_log(SITEID, 'blog', 'add', 'index.php?userid='.$post->userid.'&postid='.$post->id, $post->subject); } else { @@ -203,8 +267,26 @@ * @todo complete documenting this function. enable trackback and pingback between entries on the same server */ function do_edit($post, $blogeditform) { + global $CFG, $USER, $returnurl, $DB; + //check to see if it is a submitted assignment + if($blogassignment = $DB->get_record_sql('SELECT a.timedue, a.preventlate, a.emailteachers, a.var2, asi.grade, asi.id + FROM {assignment} a, {assignment_submissions} as asi WHERE + a.id = asi.assignment AND userid = '.$USER->id.' AND a.assignmenttype = \'blog\' + AND asi.data1 = \''.$post->id.'\'')) { + + //email teachers if necessary + if($blogassignment->emailteachers) { + email_teachers($DB->get_record('assignment_submissions', array('id'=>$blogassignment['id']))); + } + + } else { //only update the attachment and associations if it is not a submitted assignment + + if(!empty($CFG->useassoc)) add_associations($post); + } + + $post->lastmodified = time(); if ($blogeditform->get_new_filename('attachment')) { @@ -235,7 +317,7 @@ /** * function to attach tags into a post - * @param int postid - id of the blog + * @param int postid - id of the blog post */ function add_tags_info($postid) { @@ -249,9 +331,27 @@ } } - $manual_tags = optional_param('ptags', '', PARAM_NOTAGS); - $tags = array_merge($tags, explode(',', $manual_tags)); + $manualtags = optional_param('ptags', '', PARAM_NOTAGS); + $tags = array_merge($tags, explode(',', $manualtags)); tag_set('post', $postid, $tags); } + + +function add_associations($post) { + global $DB, $USER; + + $allowaddcourseassoc = true; + blog_remove_associations_for_post($post->id); + if(!empty($post->courseassoc)) { + blog_add_association($post->id, $post->courseassoc); + $allowaddcourseassoc = false; + } + if(!empty($post->modassoc)) { + foreach($post->modassoc as $modid) { + blog_add_association($post->id, $modid, $allowaddcourseassoc); + $allowaddcourseassoc = false; //let the course be added the first time + } + } +} ?> Index: blog/edit_form.php =================================================================== RCS file: /cvsroot/moodle/moodle/blog/edit_form.php,v retrieving revision 1.16 diff -u -a -w -b -B -r1.16 edit_form.php --- blog/edit_form.php 31 Jul 2008 22:15:31 -0000 1.16 +++ blog/edit_form.php 13 Aug 2008 04:16:15 -0000 @@ -5,19 +5,38 @@ class blog_edit_form extends moodleform { function definition() { - global $CFG, $COURSE, $USER; + global $CFG, $COURSE, $USER, $DB; $mform =& $this->_form; - - $post = $this->_customdata['existing']; + if(!empty($this->_customdata['assignmentdata'])) + $assignmentdata = $this->_customdata['assignmentdata']; + $existing = $this->_customdata['existing']; $sitecontext = $this->_customdata['sitecontext']; + //determine if content elements should be deactivated for a past due blog assignment + $noedit = false; + if(!empty($assignmentdata)) + if((time() > $assignmentdata->timedue and $assignmentdata->preventlate) or $assignmentdata->grade != -1) + $noedit = true; + // the upload manager is used directly in entry processing, moodleform::save_files() is not used yet + $this->set_upload_manager(new upload_manager('attachment', true, false, $COURSE, false, 0, true, true, false)); + $mform->addElement('header', 'general', get_string('general', 'form')); + + if($noedit) { //show disabled form elements, but provide hidden elements so that the data is transferred + $mform->addElement('text', 'fakesubject', get_string('entrytitle', 'blog'), array('size'=>60, 'disabled'=>'disabled')); + $mform->addElement('textarea', 'fakesummary', get_string('entrybody', 'blog'), array('rows'=>25, 'cols'=>40, 'disabled'=>'disabled')); + $mform->setHelpButton('fakesummary', array('writing', 'richtext'), false, 'editorhelpbutton'); + $mform->addElement('hidden', 'subject'); + $mform->addElement('hidden', 'summary'); + } else { //insert normal form elements $mform->addElement('text', 'subject', get_string('entrytitle', 'blog'), 'size="60"'); + $mform->addElement('htmleditor', 'summary', get_string('entrybody', 'blog'), array('rows'=>25)); + } + $mform->setType('subject', PARAM_TEXT); $mform->addRule('subject', get_string('emptytitle', 'blog'), 'required', null, 'client'); - $mform->addElement('htmleditor', 'summary', get_string('entrybody', 'blog'), array('rows'=>25)); $mform->setType('summary', PARAM_RAW); $mform->addRule('summary', get_string('emptybody', 'blog'), 'required', null, 'client'); $mform->setHelpButton('summary', array('writing', 'richtext'), false, 'editorhelpbutton'); @@ -26,7 +45,18 @@ $mform->addElement('file', 'attachment', get_string('attachment', 'forum')); - $mform->addElement('select', 'publishstate', get_string('publishto', 'blog'), blog_applicable_publish_states()); + //disable publishstate options that are not allowed + $publishstates = array(); + $i = 0; + foreach(blog_applicable_publish_states() as $state => $desc) { + if(!empty($assignmentdata)) { + if($i <= $assignmentdata->var2) //var2 is the maximum publish state allowed + $publishstates[$state] = $desc; + } else $publishstates[$state] = $desc; //no maximum was set + + $i++; + } + $mform->addElement('select', 'publishstate', get_string('publishto', 'blog'), $publishstates); $mform->setHelpButton('publishstate', array('publish_state', get_string('publishto', 'blog'), 'blog')); @@ -42,6 +72,34 @@ $mform->setType('ptagsadd', PARAM_NOTAGS); } + $allmodnames = array(); + if (!empty($CFG->useassoc)) { + $mform->addElement('header', 'assochdr', get_string('associations', 'blog')); + $courses = get_my_courses($USER->id, 'visible DESC, fullname ASC'); + $course_names[0] = 'none'; + if(!empty($courses)) { + foreach($courses as $course) { + $course_names[$course->context->id] = $course->fullname; + $modinfo = get_fast_modinfo($course, $USER->id); + $course_context_path = $DB->get_field('context', 'path', array('id' => $course->context->id)); + + foreach($modinfo->instances as $modname => $instances) { + foreach($instances as $modid => $mod) { + $mod_context_id = $DB->get_field_select('context', 'id', + 'instanceid = '.$mod->id.' AND ' . + 'contextlevel = ' . CONTEXT_MODULE . ' AND ' . + 'path LIKE \''.$course_context_path.'/%\''); + $this->modnames[$course->context->id][$mod_context_id] = $modname . ": ".$mod->name; + $allmodnames[$mod_context_id] = $course->shortname . " - " . $modname . ": ".$mod->name; + } + } + } + } + $mform->addElement('select', 'courseassoc', get_string('course'), $course_names, 'onchange="addCourseAssociations()"'); + $selectassoc = &$mform->addElement('select', 'modassoc', get_string('managemodules'), $allmodnames); + $selectassoc->setMultiple(true); + } + $this->add_action_buttons(); $mform->addElement('hidden', 'action'); @@ -55,8 +113,209 @@ $mform->setType('id', PARAM_INT); $mform->setDefault('id', 0); + if(!empty($assignmentdata)) { //dont allow associations for blog assignments + $courseassoc = $mform->getElement('courseassoc'); + $modassoc = $mform->getElement('modassoc'); + $courseassoc->updateAttributes(array('disabled' => 'disabled')); + $modassoc->updateAttributes(array('disabled' => 'disabled')); + } + if($noedit) { //disable some other fields when editing is not allowed + $subject = $mform->getElement('subject'); + $summary = $mform->getElement('summary'); + $attachment = $mform->getElement('attachment'); + $format = $mform->getElement('format'); + $attachment->updateAttributes(array('disabled' => 'disabled')); + $format->updateAttributes(array('disabled' => 'disabled')); + } + + } + + + + + function validation($data, $files) { + global $CFG, $DB, $USER; + + $errors = array(); + + //check to see if it's part of a submitted blog assignment + if($blogassignment = $DB->get_record_sql('SELECT a.timedue, a.preventlate, a.emailteachers, a.var2, asub.grade + FROM {assignment} a, {assignment_submissions} as asub WHERE + a.id = asub.assignment AND userid = '.$USER->id.' AND a.assignmenttype = \'blog\' + AND asub.data1 = \''.$data['id'].'\'')) { + + $original = $DB->get_record('post', array('id' => $data['id'])); + //don't allow updates of the sumamry, subject, or attachment + $changed = ($original->summary != $data['summary'] || + $original->subject != $data['subject'] || + !empty($files)); + + + + //send an error if improper changes are being made + if(($changed and time() > $blogassignment->timedue and $blogassignment->preventlate = 1) or + ($changed and $blogassignment->grade != -1) or + (time() < $blogassignment->timedue and ($postaccess > $blogassignment->var2 || $postaccess == -1))) { + //too late to edit this post + if($original->subject != $data['subject']) $errors['subject'] = get_string('canteditblogassignment', 'blog'); + if($original->summary != $data['summary']) $errors['summary'] = get_string('canteditblogassignment', 'blog'); + if(!empty($files)) $errors['attachment'] = get_string('canteditblogassignment', 'blog'); + } + + //insure the publishto value is within proper constraints + $publishstates = array(); + $postaccess = -1; + $i=0; + foreach(blog_applicable_publish_states() as $state => $desc) { + if($state == $data['publishstate']) + $postaccess = $i; + $publishstates[$i++] = $state; + } + if(time() < $blogassignment->timedue and ($postaccess > $blogassignment->var2 || $postaccess == -1)) + $errors['publishto'] = get_string('canteditblogassignment', 'blog'); + + } else { + if(!$data['courseassoc'] && ($data['publishstate'] == 'course' || + $data['publishstate'] == 'group') + && !empty($CFG->useassoc)) + return array('publishstate' => get_string('mustassociatecourse', 'blog')); + } + + + //validate course association + if(!empty($data['courseassoc'])) { + $coursecontext = $DB->get_record('context', array('id' => $data['courseassoc'], 'contextlevel' => CONTEXT_COURSE)); + if($coursecontext) { //insure associated course has a valid context id + //insure the user has access to this course + if(!has_capability('moodle/course:view', $coursecontext, $USER->id)) + $errors['courseassoc'] = get_string('studentnotallowed', '', fullname($USER, true)); + } else + $errors['courseassoc'] = get_string('invalidcontextid', 'blog'); + + } + + //validate mod associations + if(!empty($data['modassoc'])) { + //insure mods are valid + foreach($data['modassoc'] as $modid) { + $modcontext = $DB->get_record('context', array('id' => $modid, 'contextlevel' => CONTEXT_MODULE)); + if($modcontext) { //insure associated mod has a valid context id + //get context of the mod's course + $path = split('/', $modcontext->path); + $coursecontext = $DB->get_record('context', array('id' => $path[3])); + + //insure only one course is associated + if(!empty($data['courseassoc'])) { + if($data['courseassoc'] != $coursecontext->id) + $errors['modassoc'] = get_string('onlyassociateonecourse', 'blog'); + } else { + $data['courseassoc'] = $coursecontext->id; } + //insure the user has access to each mod's course + if(!has_capability('moodle/course:view', $coursecontext, $USER->realuser)) + $errors['modassoc'] = get_string('studentnotallowed', '', fullname($USER, true)); + } else + $errors['modassoc'] = get_string('invalidcontextid', 'blog'); + } + } + + if($errors) return $errors; + return true; + } + + + + function display() { + $existing = $this->_customdata['existing']; + + + parent::display(); + +?> + +'; + echo ''; echo ''."\n"; print_container_start(); blocks_print_group($PAGE, $pageblocks, BLOCK_POS_RIGHT); Index: blog/header.php =================================================================== RCS file: /cvsroot/moodle/moodle/blog/header.php,v retrieving revision 1.52 diff -u -a -w -b -B -r1.52 header.php --- blog/header.php 1 Jun 2008 13:48:13 -0000 1.52 +++ blog/header.php 13 Aug 2008 04:16:15 -0000 @@ -7,6 +7,7 @@ require_once($CFG->dirroot .'/blog/blogpage.php'); require_once($CFG->libdir .'/blocklib.php'); require_once($CFG->dirroot .'/course/lib.php'); +require_once($CFG->dirroot.'/tag/lib.php'); $blockaction = optional_param('blockaction','', PARAM_ALPHA); $instanceid = optional_param('instanceid', 0, PARAM_INT); @@ -47,9 +48,7 @@ $PAGE = page_create_object($pagetype, $USER->id); } $PAGE->courseid = $courseid; -$PAGE->filtertype = $filtertype; -$PAGE->filterselect = $filterselect; -$PAGE->tagid = $tagid; +$PAGE->filters = $filters; $PAGE->init_full(); //init the BlogInfo object and the courserecord object @@ -59,9 +58,9 @@ } // Calculate the preferred width for left, right and center (both center positions will use the same) -$preferred_width_left = bounded_number(BLOCK_L_MIN_WIDTH, blocks_preferred_width($pageblocks[BLOCK_POS_LEFT]), +$preferredwidthleft = bounded_number(BLOCK_L_MIN_WIDTH, blocks_preferred_width($pageblocks[BLOCK_POS_LEFT]), BLOCK_L_MAX_WIDTH); -$preferred_width_right = bounded_number(BLOCK_R_MIN_WIDTH, blocks_preferred_width($pageblocks[BLOCK_POS_RIGHT]), +$preferredwidthright = bounded_number(BLOCK_R_MIN_WIDTH, blocks_preferred_width($pageblocks[BLOCK_POS_RIGHT]), BLOCK_R_MAX_WIDTH); // Display the blocks and allow blocklib to handle any block action requested @@ -82,17 +81,12 @@ $missingblocks = blocks_get_missing($PAGE, $pageblocks); } -if (!empty($tagid)) { - $taginstance = $DB->get_record('tag', array('id'=>$tagid)); -} elseif (!empty($tag)) { - $taginstance = tag_id($tag); -} - /// navigations /// site blogs - sitefullname -> blogs -> (?tag) -/// course blogs - sitefullname -> course fullname ->blogs ->(?tag) +/// course blogs - sitefullname -> course fullname -> (?participants->user/group) -> blogs -> (?tag) +/// mod blogs - sitefullname -> course fullname -> mod name -> (?user/group) -> blogs -> (?tag) /// group blogs - sitefullname -> course fullname ->group ->(?tag) -/// user blogs - sitefullname -> (?coursefullname) -> participants -> blogs -> (?tag) +/// user blogs - sitefullname -> (?coursefullname) -> (?mod name) -> participants -> blogs -> (?tag) $blogstring = get_string('blogs','blog'); $tagstring = get_string('tag'); @@ -104,146 +98,80 @@ $navlinks = array(); -/// This is very messy atm. - switch ($filtertype) { - case 'site': - if ($tagid || !empty($tag)) { - $navlinks[] = array('name' => $blogstring, 'link' => "index.php?filtertype=site", 'type' => 'misc'); - $navlinks[] = array('name' => "$tagstring: $taginstance->name", 'link' => null, 'type' => 'misc'); - $navigation = build_navigation($navlinks); - print_header("$SITE->shortname: $blogstring", $SITE->fullname, $navigation,'','',true,$PAGE->get_extra_header_string()); - } else { - $navlinks[] = array('name' => $blogstring, 'link' => null, 'type' => 'misc'); - $navigation = build_navigation($navlinks); - print_header("$SITE->shortname: $blogstring", $SITE->fullname, $navigation,'','',true,$PAGE->get_extra_header_string()); - } - break; +//tabs compatibility +$filtertype = 'site'; +$filterselect = $USER->id; - case 'course': - if ($tagid || !empty($tag)) { - $navlinks[] = array('name' => $blogstring, - 'link' => "index.php?filtertype=course&filterselect=$filterselect", +if(!empty($courseid)) { + $COURSE = $DB->get_record('course', array('id'=>$courseid)); + if (empty($groupid) and has_capability('moodle/course:viewparticipants', $coursecontext)) { + $navlinks[] = array('name' => get_string('participants'), + 'link' => "$CFG->wwwroot/user/index.php?id=$courseid", 'type' => 'misc'); - $navlinks[] = array('name' => "$tagstring: $taginstance->name", 'link' => null, 'type' => 'misc'); - $navigation = build_navigation($navlinks); - print_header("$course->shortname: $blogstring", $course->fullname, $navigation,'','',true,$PAGE->get_extra_header_string()); - } else { - $navlinks[] = array('name' => $blogstring, 'link' => null, 'type' => 'misc'); - $navigation = build_navigation($navlinks); - print_header("$course->shortname: $blogstring", $course->fullname, $navigation,'','',true,$PAGE->get_extra_header_string()); } - break; - case 'group': + //tabs compatibility + $filtertype = 'course'; + $filterselect = $courseid; +} - if ($thisgroup = groups_get_group($filterselect, false)) { //TODO: - if ($tagid || !empty($tag)) { - $navlinks[] = array('name' => $thisgroup->name, - 'link' => "$CFG->wwwroot/user/index.php?id=$course->id&group=$filterselect", - 'type' => 'misc'); - $navlinks[] = array('name' => $blogstring, - 'link' => "index.php?filtertype=group&filterselect=$filterselect", - 'type' => 'misc'); - $navlinks[] = array('name' => "$tagstring: $taginstance->name", 'link' => null, 'type' => 'misc'); - $navigation = build_navigation($navlinks); - print_header("$course->shortname: $blogstring", $course->fullname, $navigation,'','',true,$PAGE->get_extra_header_string()); - } else { +if(!empty($modid)) { //mod + $cm = $DB->get_record('course_modules', array('id' => $modid)); + $cm->modname = $DB->get_field('modules', 'name', array('id' => $cm->module)); + $cm->name = $DB->get_field($cm->modname, 'name', array('id' => $cm->instance)); + + //tabs compatibility + $filtertype = 'course'; + $filterselect = $cm->course; +} + +if(!empty($groupid)) { + if ($thisgroup = groups_get_group($groupid, false)) { //TODO: $navlinks[] = array('name' => $thisgroup->name, - 'link' => "$CFG->wwwroot/user/index.php?id=$course->id&group=$filterselect", + 'link' => "$CFG->wwwroot/user/index.php?id=$course->id&group=$groupid", 'type' => 'misc'); - $navlinks[] = array('name' => $blogstring, 'link' => null, 'type' => 'misc'); - $navigation = build_navigation($navlinks); - print_header("$course->shortname: $blogstring", $course->fullname, $navigation,'','',true,$PAGE->get_extra_header_string()); - } } else { print_error('cannotfindgroup'); } - break; - - case 'user': - $participants = get_string('participants'); - if (!$user = $DB->get_record('user', array('id'=>$filterselect))) { - print_error('invaliduserid'); + //tabs compatibility + $filtertype = 'group'; + $filterselect = $thisgroup->id; } - if ($course->id != SITEID) { - $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id); // Course context - $systemcontext = get_context_instance(CONTEXT_SYSTEM); // SYSTEM context - - if (has_capability('moodle/course:viewparticipants', $coursecontext) || has_capability('moodle/site:viewparticipants', $systemcontext)) { - $navlinks[] = array('name' => $participants, - 'link' => "$CFG->wwwroot/user/index.php?id=$course->id", - 'type' => 'misc'); - } +if(!empty($userid)) { + $user = $DB->get_record('user', array('id'=>$userid)); $navlinks[] = array('name' => fullname($user), - 'link' => "$CFG->wwwroot/user/view.php?id=$filterselect&course=$course->id", + 'link' => "$CFG->wwwroot/user/view.php?id=$userid".(empty($courseid)?'':"&course=$courseid"), 'type' => 'misc'); - if ($tagid || !empty($tag)) { - $navlinks[] = array('name' => $blogstring, - 'link' => "index.php?courseid=$course->id&filtertype=user&filterselect=$filterselect", - 'type' => 'misc'); - $navlinks[] = array('name' => "$tagstring: $taginstance->name", 'link' => null, 'type' => 'misc'); - $navigation = build_navigation($navlinks); - - } else { - $navlinks[] = array('name' => $blogstring, 'link' => null, 'type' => 'misc'); - $navigation = build_navigation($navlinks); + //tabs compatibility + $filtertype = 'user'; + $filterselect = $user->id; } - print_header("$course->shortname: $blogstring", $course->fullname, $navigation,'','',true,$PAGE->get_extra_header_string()); - - } else { - //in top view - - if ($postid) { - $navlinks[] = array('name' => fullname($user), - 'link' => "$CFG->wwwroot/user/view.php?id=$filterselect", - 'type' => 'misc'); - $navlinks[] = array('name' => $blogstring, - 'link' => "index.php?filtertype=user&filterselect=$filterselect", - 'type' => 'misc'); - $navlinks[] = array('name' => format_string($postobject->subject), 'link' => null, 'type' => 'misc'); - $navigation = build_navigation($navlinks); +$navlinks[] = array('name' => $blogstring, 'link' => null, 'type' => 'misc'); - } else if ($tagid || !empty($tag)) { - $navlinks[] = array('name' => fullname($user), - 'link' => "$CFG->wwwroot/user/view.php?id=$filterselect", - 'type' => 'misc'); - $navlinks[] = array('name' => $blogstring, - 'link' => "index.php?filtertype=user&filterselect=$filterselect", - 'type' => 'misc'); - $navlinks[] = array('name' => "$tagstring: $taginstance->name", 'link' => null, 'type' => 'misc'); - $navigation = build_navigation($navlinks); - } else { - $navlinks[] = array('name' => fullname($user), - 'link' => "$CFG->wwwroot/user/view.php?id=$filterselect", +if(!empty($tagid)) { + $tagrec = $DB->get_record('tag', array('id'=>$tagid)); + $navlinks[] = array('name' => $tagrec->name, + 'link' => "index.php", 'type' => 'misc'); - $navlinks[] = array('name' => $blogstring, 'link' => null, 'type' => 'misc'); - $navigation = build_navigation($navlinks); } - print_header("$SITE->shortname: $blogstring", $SITE->fullname, $navigation,'','',true,$PAGE->get_extra_header_string()); - } - break; +if(isset($cm)) $navigation = build_navigation($navlinks, $cm); +else $navigation = build_navigation($navlinks); - default: - error ('Error unknown filtertype'); - break; - } +print_header("$COURSE->shortname: $blogstring", $COURSE->fullname, $navigation,'','',true,$PAGE->get_extra_header_string()); // prints the tabs -if ($filtertype=='user') { - $showroles = true; -} else { - $showroles = false; -} +$showroles = !empty($userid); $currenttab = 'blogs'; +$user = $USER; require_once($CFG->dirroot .'/user/tabs.php'); @@ -253,7 +181,7 @@ /// The left column ... if (blocks_have_content($pageblocks, BLOCK_POS_LEFT) || $editing) { - print '' . "\n"; + print '' . "\n"; print '' . "\n"; print_container_start(); blocks_print_group($PAGE, $pageblocks, BLOCK_POS_LEFT); Index: blog/index.php =================================================================== RCS file: /cvsroot/moodle/moodle/blog/index.php,v retrieving revision 1.44 diff -u -a -w -b -B -r1.44 index.php --- blog/index.php 24 Jul 2008 04:59:29 -0000 1.44 +++ blog/index.php 13 Aug 2008 04:16:15 -0000 @@ -13,15 +13,31 @@ $id = optional_param('id', 0, PARAM_INT); $start = optional_param('formstart', 0, PARAM_INT); $userid = optional_param('userid', 0, PARAM_INT); +$postid = optional_param('postid', 0, PARAM_INT); +$groupid = optional_param('groupid', 0, PARAM_INT); +$modid = optional_param('modid', 0, PARAM_INT); $tag = optional_param('tag', '', PARAM_NOTAGS); $tagid = optional_param('tagid', 0, PARAM_INT); -$postid = optional_param('postid', 0, PARAM_INT); -$filtertype = optional_param('filtertype', '', PARAM_ALPHA); -$filterselect = optional_param('filterselect', 0, PARAM_INT); - $edit = optional_param('edit', -1, PARAM_BOOL); $courseid = optional_param('courseid', 0, PARAM_INT); // needed for user tabs and course tracking +//correct tagid if a text tag is provided as a param +if(!empty($tag)) { //text tag parameter takes precedence + if ($tagrec = $DB->get_record_sql("SELECT * FROM {tag} WHERE name LIKE ?", array($tag))) { + $tagid = $tagrec->id; + } else { + unset($tagid); + } +} + +//add courseid if modid or groupid is specified +if(!empty($modid) and empty($courseid)) { + $courseid = $DB->get_field('course_modules', 'course', array('id'=>$modid)); +} + +if(!empty($groupid) and empty($courseid)) { + $courseid = $DB->get_field('groups', 'courseid', array('id'=>$groupid)); +} if (empty($CFG->bloglevel)) { print_error('blogdisable', 'blog'); @@ -35,33 +51,31 @@ $SESSION->blog_editing_enabled = $edit; } -if (empty($filtertype)) { - if ($userid) { // default to user if specified - $filtertype = 'user'; - $filterselect = $userid; - } else if (has_capability('moodle/blog:view', $sitecontext) and $CFG->bloglevel > BLOG_USER_LEVEL) { +if (!$userid and has_capability('moodle/blog:view', $sitecontext) and $CFG->bloglevel > BLOG_USER_LEVEL) { if ($postid) { - $filtertype = 'user'; if (!$postobject = $DB->get_record('post', array('module'=>'blog', 'id'=>$postid))) { print_error('nosuchentry', 'blog'); } - $filterselect = $postobject->userid; - } else { - $filtertype = 'site'; - $filterselect = ''; + $userid = $postobject->userid; } - } else { +} else if(!$userid) { // user might have capability to write blogs, but not read blogs at site level // users might enter this url manually without parameters - $filtertype = 'user'; - $filterselect = $USER->id; - } + $userid = $USER->id; } /// check access and prepare filters -switch ($filtertype) { +if(!empty($modid)) { //check mod access + if ($CFG->bloglevel < BLOG_COURSE_LEVEL) { + print_error(get_string('nocourseblogs', 'blog')); + } + if (!$mod = $DB->get_record('course_modules', array('id' => $modid))) { + print_error(get_string('invalidmodid', 'blog')); + } + $courseid = $mod->course; +} - case 'site': +if((empty($courseid) ? true : $courseid == SITEID) and empty($userid)) { //check site access if ($CFG->bloglevel < BLOG_SITE_LEVEL) { print_error('siteblogdisable', 'blog'); } @@ -71,13 +85,16 @@ if (!has_capability('moodle/blog:view', $sitecontext)) { print_error('cannotviewsiteblog', 'blog'); } - break; - case 'course': - if ($CFG->bloglevel < BLOG_COURSE_LEVEL) { - print_error('courseblogdisable', 'blog'); + $COURSE = $DB->get_record('course', array('format'=>'site')); + $courseid = $COURSE->id; } - if (!$course = $DB->get_record('course', array('id'=>$filterselect))) { + +if(!empty($courseid)) { +// if ($CFG->bloglevel < BLOG_COURSE_LEVEL) { +// print_error('courseblogdisable', 'blog'); +// } + if (!$course = $DB->get_record('course', array('id'=>$courseid))) { print_error('invalidcourseid'); } $courseid = $course->id; @@ -86,40 +103,41 @@ if (!has_capability('moodle/blog:view', $coursecontext)) { print_error('cannotviewcourseblog', 'blog'); } - break; +} else { + $coursecontext = get_context_instance(CONTEXT_COURSE, SITEID); +} - case 'group': +if(!empty($groupid)) { if ($CFG->bloglevel < BLOG_GROUP_LEVEL) { print_error('groupblogdisable', 'blog'); } // fix for MDL-9268 - if (! $group = groups_get_group($filterselect)) { //TODO:check. - print_error('invalidgroupid'); + if (! $group = groups_get_group($groupid)) { //TODO:check. + print_error(get_string('invalidgroupid', 'blog')); } if (!$course = $DB->get_record('course', array('id'=>$group->courseid))) { - print_error('invalidcourseid'); + print_error(get_string('invalidcourseid', 'blog')); } $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id); $courseid = $course->id; require_login($course); if (!has_capability('moodle/blog:view', $coursecontext)) { - print_error('cannotviewcourseorgroupblog', 'blog'); + print_error(get_string('cannotviewcourseorgroupblog', 'blog')); } if (groups_get_course_groupmode($course) == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $coursecontext)) { - if (!groups_is_member($filterselect)) { + if (!groups_is_member($groupid)) { print_error('notmemberofgroup'); } } +} - break; - - case 'user': +if(!empty($user)) { if ($CFG->bloglevel < BLOG_USER_LEVEL) { print_error('blogdisable', 'blog'); } - if (!$user = $DB->get_record('user', array('id'=>$filterselect))) { + if (!$user = $DB->get_record('user', array('id'=>$userid))) { print_error('invaliduserid'); } if ($user->deleted) { @@ -129,43 +147,39 @@ die; } - if ($USER->id == $filterselect) { + if ($USER->id == $userid) { if (!has_capability('moodle/blog:create', $sitecontext) and !has_capability('moodle/blog:view', $sitecontext)) { print_error('donothaveblog', 'blog'); } } else { - $personalcontext = get_context_instance(CONTEXT_USER, $filterselect); + $personalcontext = get_context_instance(CONTEXT_USER, $userid); if (!has_capability('moodle/blog:view', $sitecontext) and !has_capability('moodle/user:readuserblogs', $personalcontext)) { print_error('cannotviewuserblog', 'blog'); } - if (!blog_user_can_view_user_post($filterselect)) { + if (!blog_user_can_view_user_post($userid)) { print_error('cannotviewcourseblog', 'blog'); } } - $userid = $filterselect; - - if (!empty($courseid)) { - require_login($courseid); - } - - break; - - default: - print_error('incorrectblogfilter', 'blog'); - break; } if (empty($courseid)) { $courseid = SITEID; } +if(!empty($postid)) $filters['post'] = $postid; +if(!empty($courseid)) $filters['course'] = $courseid; +if(!empty($modid)) $filters['mod'] = $modid; +if(!empty($groupid)) $filters['group'] = $groupid; +if(!empty($userid)) $filters['user'] = $userid; +if(!empty($tagid)) $filters['tag'] = $tagid; + include($CFG->dirroot .'/blog/header.php'); -blog_print_html_formatted_entries($postid, $filtertype, $filterselect, $tagid, $tag); +blog_print_html_formatted_entries($filters); -add_to_log($courseid, 'blog', 'view', 'index.php?filtertype='.$filtertype.'&filterselect='.$filterselect.'&postid='.$postid.'&tagid='.$tagid.'&tag='.$tag, 'view blog entry'); +add_to_log($courseid, 'blog', 'view', blog_get_blogs_url($filters), 'view blog entry'); include($CFG->dirroot .'/blog/footer.php'); Index: blog/lib.php =================================================================== RCS file: /cvsroot/moodle/moodle/blog/lib.php,v retrieving revision 1.100 diff -u -a -w -b -B -r1.100 lib.php --- blog/lib.php 31 Jul 2008 22:15:31 -0000 1.100 +++ blog/lib.php 13 Aug 2008 04:16:16 -0000 @@ -70,9 +70,9 @@ * * $@param ... */ - function blog_print_html_formatted_entries($postid, $filtertype, $filterselect, $tagid, $tag) { + function blog_print_html_formatted_entries($filters) { - global $CFG, $USER; + global $CFG, $USER, $PAGE; $blogpage = optional_param('blogpage', 0, PARAM_INT); $bloglimit = optional_param('limit', get_user_preferences('blogpagesize', 10), PARAM_INT); @@ -82,19 +82,24 @@ $morelink = '
      '; - $totalentries = get_viewable_entry_count($postid, $bloglimit, $start, $filtertype, $filterselect, $tagid, $tag, $sort='created DESC'); - $blogEntries = blog_fetch_entries($postid, $bloglimit, $start, $filtertype, $filterselect, $tagid, $tag, $sort='created DESC', true); + $blogEntries = blog_fetch_entries($bloglimit, $start, $filters, $sort='created DESC', true); + $totalentries = blog_get_viewable_entry_count($filters); - print_paging_bar($totalentries, $blogpage, $bloglimit, get_baseurl($filtertype, $filterselect), 'blogpage'); + print_paging_bar($totalentries, $blogpage, $bloglimit, blog_get_blogs_url($filters), 'blogpage'); if ($CFG->enablerssfeeds) { - blog_rss_print_link($filtertype, $filterselect, $tag); + blog_rss_print_link($filters); } if (has_capability('moodle/blog:create', $sitecontext)) { //the user's blog is enabled and they are viewing their own blog + $coursearg = ''; + if(!empty($PAGE->filters['course'])) { + $coursearg = '&courseid='.$PAGE->filters['course']; + if(!empty($PAGE->filters['mod'])) $coursearg .= '&modid='.$PAGE->filters['mod']; + } $addlink = '
    '; echo $addlink; } @@ -103,11 +108,11 @@ $count = 0; foreach ($blogEntries as $blogEntry) { - blog_print_entry($blogEntry, 'list', $filtertype, $filterselect); //print this entry. + blog_print_entry($blogEntry, 'list', $filters); //print this entry. $count++; } - print_paging_bar($totalentries, $blogpage, $bloglimit, get_baseurl($filtertype, $filterselect), 'blogpage'); + print_paging_bar($totalentries, $blogpage, $bloglimit, blog_get_blogs_url($filters), 'blogpage'); if (!$count) { print '
    '. get_string('noentriesyet', 'blog') .'

    '; @@ -140,7 +145,7 @@ * in its complete form (eg. archive page). If anything other than 'full' * display the entry in its abbreviated format (eg. index page) */ - function blog_print_entry($blogEntry, $viewtype='full', $filtertype='', $filterselect='', $mode='loud') { + function blog_print_entry($blogEntry, $viewtype='full', $filters=array(), $mode='loud') { global $USER, $CFG, $COURSE, $ME, $DB; $template['body'] = format_text($blogEntry->summary, $blogEntry->format); @@ -170,9 +175,20 @@ $user = $DB->get_record('user', array('id'=>$template['userid'])); + //check to see if the post is unassociated with group/course level access + $unassociatedpost = false; + if(!empty($CFG->useassoc) && ($blogEntry->publishstate == 'group' || + $blogEntry->publishstate == 'course')) { + if(!$DB->record_exists('blog_association', array('blogid' => $blogEntry->id))) { + $unassociatedpost = true; + } + } + /// Start printing of the blog - echo ''; + + echo '
    '; echo '
    '; print_user_picture($user, SITEID, $user->picture); @@ -205,6 +221,14 @@ case 'draft': $blogtype = get_string('publishtonoone', 'blog'); break; + case 'course': + $blogtype = !empty($CFG->useassoc) ? get_string('publishtocourseassoc', 'blog') + : get_string('publishtocourse', 'blog'); + break; + case 'group': + $blogtype = !empty($CFG->useassoc) ? get_string('publishtogroupassoc', 'blog') + : get_string('publishtogroup', 'blog'); + break; case 'site': $blogtype = get_string('publishtosite', 'blog'); break; @@ -234,13 +258,52 @@ echo ''; } + //add associations + if ( !empty($CFG->useassoc) && $blog_associations = $DB->get_records('blog_association', array('blogid' => $blogEntry->id))) { + echo '
    '; + $assoc_str = ''; + foreach($blog_associations as $assoc_rec) { //first find and show the associated course + $context_rec = $DB->get_record('context', array('id' => $assoc_rec->contextid)); + if($context_rec->contextlevel == CONTEXT_COURSE) { + $assoc_str .= ''; + $assoc_str .= ''; + $assoc_str .= $DB->get_field('course', 'shortname', array('id' => $context_rec->instanceid)); + $assoc_str .= ''; + } + } + foreach($blog_associations as $assoc_rec) { //now show each mod association + $context_rec = $DB->get_record('context', array('id' => $assoc_rec->contextid)); + if($context_rec->contextlevel == CONTEXT_MODULE) { + $modinfo = $DB->get_record('course_modules', array('id' => $context_rec->instanceid)); + $modname = $DB->get_field('modules', 'name', array('id' => $modinfo->module)); + $assoc_str .= ', '; + $assoc_str .= ''; + $assoc_str .= ''; + $assoc_str .= $DB->get_field($modname, 'name', array('id' => $modinfo->instance)); + $assoc_str .= ''; + } + } + echo get_string('associations', 'blog') . ': '. $assoc_str; + + echo '
    '; + } + + if($unassociatedpost) { + echo '
    '.get_string('associationunviewable', 'blog').'
    '; + } + /// Commands echo '
    '; if (blog_user_can_edit_post($blogEntry)) { echo ''.$stredit.''; - echo '| '.$strdelete.' | '; + if(!$DB->record_exists_sql('SELECT a.timedue, a.preventlate, a.emailteachers, a.var2, asub.grade + FROM {assignment} a, {assignment_submissions} as asub WHERE + a.id = asub.assignment AND userid = '.$USER->id.' AND a.assignmenttype = \'blog\' + AND asub.data1 = \''.$blogEntry->id.'\'')) + echo '| '.$strdelete.''; + echo ' | '; } echo ''.get_string('permalink', 'blog').''; @@ -338,7 +401,17 @@ $options = array ( 'draft' => get_string('publishtonoone', 'blog') ); } - if ($CFG->bloglevel > BLOG_USER_LEVEL) { + if ($CFG->bloglevel >= BLOG_GROUP_LEVEL) { + $options['group'] = empty($CFG->useassoc) ? get_string('publishtogroupassoc', 'blog') + : get_string('publishtogroup', 'blog'); + } + + if ($CFG->bloglevel >= BLOG_COURSE_LEVEL) { + $options['course'] = !empty($CFG->useassoc) ? get_string('publishtocourseassoc', 'blog') + : get_string('publishtocourse', 'blog'); + } + + if ($CFG->bloglevel >= BLOG_SITE_LEVEL) { $options['site'] = get_string('publishtosite', 'blog'); } @@ -462,30 +535,16 @@ /** - * Main filter function. + * Generates an SQL query for retrieving blog entries */ - function blog_fetch_entries($postid='', $fetchlimit=10, $fetchstart='', $filtertype='', $filterselect='', $tagid='', $tag ='', $sort='lastmodified DESC', $limit=true) { + function blog_fetch_entries_sql($fetchlimit=10, $fetchstart='', $filters=array(), $sort='lastmodified DESC', $limit=true) { global $CFG, $USER, $DB; - /// the post table will be used for other things too - $typesql = "AND p.module = 'blog'"; - - /// set the tag id for searching - if ($tagid) { - $tag = $tagid; - } else if ($tag) { - if ($tagrec = $DB->get_record_sql("SELECT * FROM {tag} WHERE name LIKE ?", array($tag))) { - $tag = $tagrec->id; - } else { - $tag = -1; //no records found - } - } - - // If we have specified an ID + // If we have specified a post ID // Just return 1 entry - if ($postid) { - if ($post = $DB->get_record('post', array('id'=>$postid))) { + if (!empty($filters['post'])) { + if ($post = $DB->get_record('post', array('id'=>$filters['post']))) { if (blog_user_can_view_user_post($post->userid, $post)) { @@ -505,96 +564,148 @@ } } - $params = array(); + // The query used to locate blog entries is complicated. It will be built from the following components: + $requiredfields = "p.*, u.firstname,u.lastname,u.email"; // the SELECT clause + $tables = array('p' => 'post', 'u' => 'user'); // components of the FROM clause (table_id => table_name) + $conditions = array('u.deleted = 0', 'p.userid = u.id', 'p.module = \'blog\''); // components of the WHERE clause (conjunction) - if ($tag) { - $tagtablesql = ", {tag_instance} ti"; - $tagquerysql = "AND ti.itemid = p.id AND ti.tagid = :tag AND ti.itemtype = 'post'"; - $params['tag'] = $tag; - } else { - $tagtablesql = ''; - $tagquerysql = ''; + if (!empty($filters['tag'])) { + $tables['ti'] = 'tag_instance'; + $conditions[] = 'ti.itemid = p.id'; + $conditions[] = 'ti.tagid = '.$filters['tag']; + $conditions[] = 'ti.itemtype = \'post\''; } - if (isloggedin() && !has_capability('moodle/legacy:guest', get_context_instance(CONTEXT_SYSTEM), $USER->id, false)) { - $permissionsql = "AND (p.publishstate = 'site' OR p.publishstate = 'public' OR p.userid = :userid)"; - $params['userid'] = $USER->id; - } else { - $permissionsql = "AND p.publishstate = 'public'"; - } + + // build up a clause for permission constraints // fix for MDL-9165, use with readuserblogs capability in a user context can read that user's private blogs // admins can see all blogs regardless of publish states, as described on the help page if (has_capability('moodle/user:readuserblogs', get_context_instance(CONTEXT_SYSTEM))) { - $permissionsql = ''; - } else if ($filtertype=='user' && has_capability('moodle/user:readuserblogs', get_context_instance(CONTEXT_USER, $filterselect))) { - $permissionsql = ''; - } - /**************************************** - * depending on the type, there are 4 * - * different possible sqls * - ****************************************/ + // don't add permission constraints + } else if(!empty($filters['user']) && + has_capability('moodle/user:readuserblogs', + get_context_instance(CONTEXT_USER, (empty($filters['user']) ? 0 : $filters['user'])))) { + // don't add permission constraints + } else { - $requiredfields = "p.*, u.firstname,u.lastname,u.email"; - if ($filtertype == 'course' && $filterselect == SITEID) { // Really a site - $filtertype = 'site'; + + if (isloggedin() && !has_capability('moodle/legacy:guest', get_context_instance(CONTEXT_SYSTEM, SITEID), $USER->id, false)) { + $usergroups = ''; + $usercourses = ''; + $assocexists = $DB->record_exists('blog_association', array()); //dont check association records if there aren't any + + foreach($DB->get_records('groups_members', array('userid' => $USER->id)) as $rec) { + $usergroups .= ($usergroups ? ', ' : '') . $rec->groupid; + } + foreach(get_my_courses($USER->id) as $course) { + $usercourses .= ($usercourses ? ', ' : '') . $course->context->id; } - switch ($filtertype) { - case 'site': + if(!empty($filter['course'])) { //optimization to make searches faster + $filtercontext = get_context_instance(CONTEXT_COURSE, $filter['course']); + if(!in_array($filtercontext->id, $usercourses)) return array(); + if(!empty($filter['group'])) { + if(!in_array($filters['group'], $usergroups)) return array(); + } + } - $SQL = "SELECT $requiredfields - FROM {post} p, {user} u $tagtablesql - WHERE p.userid = u.id $tagquerysql - AND u.deleted = 0 - $permissionsql $typesql"; - break; + $permissionsql = '(p.userid = '.$USER->id.' '; - case 'course': - // all users with a role assigned - $context = get_context_instance(CONTEXT_COURSE, $filterselect); + if($CFG->bloglevel >= BLOG_SITE_LEVEL) { // add permission to view site-level posts + $permissionsql .= ' OR p.publishstate = \'site\' '; + } - // MDL-10037, hidden users' blogs should not appear - if (has_capability('moodle/role:viewhiddenassigns', $context)) { - $hiddensql = ''; + if($CFG->bloglevel >= BLOG_GLOBAL_LEVEL) { + $permissionsql .= ' OR p.publishstate = \'public\' '; + } + + if(empty($CFG->useassoc)) { // insure viewer shares *any* course/group with the poster + if($usergroups and $CFG->bloglevel >= BLOG_GROUP_LEVEL) { + $tables['gm'] = 'groups_members'; + $permissionsql .= ' OR (p.publishstate = \'group\' '. + ' AND gm.userid = p.userid AND gm.groupid IN ('.$usergroups.'))'; + } + if($usercourses and $CFG->bloglevel >= BLOG_COURSE_LEVEL) { + $tables['ra'] = 'role_assignments'; + $permissionsql .= ' OR (p.publishstate = \'course\' '. + ' AND p.userid = ra.userid AND ra.contextid IN ('.$usercourses.'))'; + } + } else if($assocexists) { // insure viewer has access to the associated course (if course or group level access is used) + if($usercourses and $CFG->bloglevel >= BLOG_COURSE_LEVEL) { + $tables['ba'] = 'blog_association'; + $permissionsql .=' OR (p.publishstate = \'course\' AND p.id = ba.blogid AND ba.contextid IN ('.$usercourses.'))'; + } + if($usergroups and $CFG->bloglevel >= BLOG_GROUP_LEVEL) { + $tables['gma'] = 'groups_members'; + $tables['gmb'] = 'groups_members'; + $tables['ba'] = 'blog_association'; + $permissionsql .= ' OR (p.publishstate = \'group\' AND p.id = ba.blogid AND ba.contextid IN ('.$usercourses.') + AND gma.groupid = gmb.groupid AND gma.userid = '.$USER->id.' AND gmb.userid = p.userid) '; + } + } + $permissionsql .= ') '; } else { - $hiddensql = 'AND ra.hidden = 0'; + $permissionsql = "p.publishstate = 'site'"; + } + $conditions[] = $permissionsql; //add permission constraints } - $SQL = "SELECT $requiredfields - FROM {post} p, {user} u, {role_assignments} ra $tagtablesql - WHERE p.userid = ra.userid $tagquerysql - AND ra.contextid ".get_related_contexts_string($context)." - AND u.id = p.userid - AND u.deleted = 0 - $hiddensql $permissionsql $typesql"; + if (!empty($filters['course'])) { + if($filters['course'] == SITEID) { // Really a site + $filters['site'] = true; + unset($filters['course']); + } + } - break; + $specificsql = ''; + if(!empty($filters['site'])) { //view posts for the whole site + //no constraints to add in this case + } - case 'group': + if(!empty($filters['mod'])) { //only view posts associated with a particular mod + $context = get_context_instance(CONTEXT_MODULE, $filters['mod']); + $tables['ba'] = 'blog_association'; + $conditions[] = 'p.id = ba.blogid'; + $conditions[] = 'ba.contextid = '.$context->id; + } - $SQL = "SELECT $requiredfields - FROM {post} p, {user} u, {groups_members} gm $tagtablesql - WHERE p.userid = gm.userid AND u.id = p.userid $tagquerysql - AND gm.groupid = :groupid - AND u.deleted = 0 - $permissionsql $typesql"; - $params['groupid'] = $filterselect; - break; - - case 'user': - - $SQL = "SELECT $requiredfields - FROM {post} p, {user} u $tagtablesql - WHERE p.userid = u.id $tagquerysql - AND u.id = :uid - AND u.deleted = 0 - $permissionsql $typesql"; - $params['uid'] = $filterselect; - break; + if(!empty($filters['course'])) { // view posts for all members of a course + $tables['ra'] = 'role_assignments'; + $context = get_context_instance(CONTEXT_COURSE, $filters['course']); + + // MDL-10037, hidden users' blogs should not appear + if (!has_capability('moodle/role:viewhiddenassigns', $context)) { + $conditions[] = 'ra.hidden = 0'; + } + + $conditions[] = 'p.userid = ra.userid'; + $conditions[] = 'ra.contextid '.get_related_contexts_string($context); + if(!empty($CFG->useassoc) && empty($filters['mod'])) { // only show blog entries associated with this course + $tables['ba'] = 'blog_association'; + $conditions[] = 'p.id = ba.blogid'; + $conditions[] = 'ba.contextid = '.$context->id; + } + } + + if(!empty($filters['group'])) { // view posts for all members of a group + $tables['gm'] = 'groups_members'; + $conditions[] = 'p.userid = gm.userid'; + $conditions[] = 'gm.groupid = '.$filters['group']; + if(!empty($CFG->useassoc)) { // only show blog entries associated with this course + $tables['ba'] = 'blog_association'; + $course_context = get_context_instance(CONTEXT_COURSE, $DB->get_field('groups', 'courseid', array('id' => $filters['group']))); + $conditions[] = 'gm.groupid = '.$filters['group']; + $conditions[] = 'ba.contextid = '.$course_context->id; + $conditions[] = 'ba.blogid = p.id'; + } + } + + if(!empty($filters['user'])) { // view posts for a single user + $conditions[] = 'u.id = '.$filters['user']; } $limitfrom = 0; @@ -605,75 +716,63 @@ $limitnum = $fetchlimit; } - $orderby = "ORDER BY $sort"; - - $records = $DB->get_records_sql("$SQL $orderby", $params, $limitfrom, $limitnum); - - if (empty($records)) { - return array(); + $tablessql = ''; // build up the FROM clause + foreach($tables as $tablename => $table) { + $tablessql .= ($tablessql ? ', ' : '').'{'.$table.'} '.$tablename; } - return $records; + $conditionssql = ''; // build up the WHERE clause + foreach($conditions as $condition) { + $conditionssql .= ($conditionssql ? ' AND ' : '').$condition; } + return 'SELECT '.$requiredfields.' FROM '.$tablessql.' WHERE '.$conditionssql.' GROUP BY p.id ORDER BY '. $sort; + } /** - * get the count of viewable entries, easiest way is to count blog_fetch_entries - * this is used for print_paging_bar - * this is not ideal, but because of the UNION in the sql in blog_fetch_entries, - * it is hard to use $DB->count_records_sql + * Main filter function */ - function get_viewable_entry_count($postid='', $fetchlimit=10, - $fetchstart='', $filtertype='', $filterselect='', $tagid='', - $tag ='', $sort='lastmodified DESC') { - - $blogEntries = blog_fetch_entries($postid, $fetchlimit, - $fetchstart, $filtertype, $filterselect, $tagid, $tag, - $sort='lastmodified DESC', false); + function blog_fetch_entries($fetchlimit=10, $fetchstart='', $filters=array(), $sort='lastmodified DESC', $limit=true) { + global $DB; + $limitfrom = 0; + $limitnum = 0; - return count($blogEntries); + if ($fetchstart !== '' && $limit) { + $limitfrom = $fetchstart; + $limitnum = $fetchlimit; } + $SQL = blog_fetch_entries_sql($fetchlimit, $fetchstart, $filters, $sort, $limit); + $records = $DB->get_records_sql($SQL, array(), $limitfrom, $limitnum); + if (empty($records)) { + return array(); + } - /// Find the base url from $_GET variables, for print_paging_bar - function get_baseurl($filtertype, $filterselect) { - - $getcopy = $_GET; + return $records; + } - unset($getcopy['blogpage']); + function blog_get_viewable_entry_count($filters=array()) { + global $DB; + $SQL = blog_fetch_entries_sql(1,0,$filters,'lastmodified DESC',false); - $strippedurl = strip_querystring(qualified_me()); - if(!empty($getcopy)) { - $first = false; - $querystring = ''; - foreach($getcopy as $var => $val) { - if(!$first) { - $first = true; - if ($var != 'filterselect' && $var != 'filtertype') { - $querystring .= '?'.$var.'='.$val; - $hasparam = true; - } else { - $querystring .= '?'; - } - } else { - if ($var != 'filterselect' && $var != 'filtertype') { - $querystring .= '&'.$var.'='.$val; - $hasparam = true; - } - } - } - if (isset($hasparam)) { - $querystring .= '&'; - } else { - $querystring = '?'; - } - } else { - $querystring = '?'; + //cut out the select statement and the group by and order by statements: + $chunks = split('(FROM)|(GROUP)', $SQL); //the middle chunk (id: 1) is the one we want + //the following groups all rows together, since all 'module' values will be 'blog' + $SQL = 'SELECT COUNT(*) FROM ' . $chunks[1] . ' GROUP BY module'; + return $DB->count_records_sql($SQL); } - return strip_querystring(qualified_me()) . $querystring. 'filtertype='. - $filtertype.'&filterselect='.$filterselect.'&'; + function blog_get_blogs_url($filters) { + global $CFG; + return $CFG->wwwroot.'/blog/index.php?'. + (empty($filters['course']) ? '' : 'courseid='.$filters['course'].'&'). + (empty($filters['mod']) ? '' : 'modid='.$filters['mod'].'&'). + (empty($filters['group']) ? '' : 'groupid='.$filters['group'].'&'). + (empty($filters['user']) ? '' : 'userid='.$filters['user'].'&'). + (empty($filters['post']) ? '' : 'postid='.$filters['post'].'&'). + (empty($filters['tag']) ? '' : 'tagid='.$filters['tag'].'&'). + (empty($filters['tagtext']) ? '' : 'tag='.$filters['tagtext']); } /** @@ -687,4 +786,39 @@ FROM {post} WHERE module = 'blog' AND courseid = 0"); } + + + /** + * add a single association for a blog entry + * @param int blogid - id of blog post + */ + function blog_add_association($blogid, $contextid, $allow_add_course = true) { + global $DB; + + $assoc_object = new StdClass; + $assoc_object->contextid = $contextid; + $assoc_object->blogid = $blogid; + $DB->insert_record('blog_association', $assoc_object); + } + + /** + * remove all associations for a blog post + * @param int blogid - id of the blog post + */ + function blog_remove_associations_for_post($blogid) { + global $DB; + $DB->delete_records('blog_association', array('blogid' => $blogid)); + } + + /** + * remove all associations for the blog posts of a particular user + * @param int userid - id of user whose blog associations will be deleted + */ + function blog_remove_associations_for_user($userid) { + global $DB; + foreach(blog_fetch_entries(0,0,array('user' => $userid), 'lasmodified DESC', false) as $post) { + blog_remove_associations_for_post($post->id); + } + } + ?> Index: course/lib.php =================================================================== RCS file: /cvsroot/moodle/moodle/course/lib.php,v retrieving revision 1.612 diff -u -a -w -b -B -r1.612 lib.php --- course/lib.php 8 Aug 2008 05:25:54 -0000 1.612 +++ course/lib.php 13 Aug 2008 04:16:18 -0000 @@ -2355,6 +2355,7 @@ function delete_course_module($id) { global $CFG, $DB; require_once($CFG->libdir.'/gradelib.php'); + require_once($CFG->dirroot.'/blog/lib.php'); if (!$cm = $DB->get_record('course_modules', array('id'=>$id))) { return true; @@ -2374,7 +2375,9 @@ } } - return $DB->delete_records('course_modules', array('id'=>$cm->id)); + $context = get_context_instance(CONTEXT_MODULE, $id); + return $DB->delete_records('course_modules', array('id'=>$cm->id)) && + $DB->delete_records('blog_association', array('contextid'=>$context->id)); } function delete_mod_from_section($mod, $section) { Index: lang/en_utf8/admin.php =================================================================== RCS file: /cvsroot/moodle/moodle/lang/en_utf8/admin.php,v retrieving revision 1.218 diff -u -a -w -b -B -r1.218 admin.php --- lang/en_utf8/admin.php 7 Aug 2008 22:56:34 -0000 1.218 +++ lang/en_utf8/admin.php 13 Aug 2008 04:16:19 -0000 @@ -781,6 +781,8 @@ $string['webproxyinfo'] = 'Fill in following options if your Moodle server can not access internet directly. Internet access is required for download of environment data, language packs, RSS feeds, timezones, etc.
    PHP cURL extension is highly recommended.'; $string['xmlrpcrecommended'] = 'Installing the optional xmlrpc extension is useful for Moodle Networking functionality.'; $string['xmlstrictheaders'] = 'XML strict headers'; +$string['useassoc'] = 'Enable associations'; +$string['configuseassoc'] = 'Should users be able to organize their blog by associating entries with courses and course modules?'; $string['ziprequired'] = 'The Zip PHP extension is now required by Moodle, info-ZIP binaries or PclZip library are not used anymore.'; ?> Index: lang/en_utf8/assignment.php =================================================================== RCS file: /cvsroot/moodle/moodle/lang/en_utf8/assignment.php,v retrieving revision 1.27 diff -u -a -w -b -B -r1.27 assignment.php --- lang/en_utf8/assignment.php 22 May 2008 07:24:35 -0000 1.27 +++ lang/en_utf8/assignment.php 13 Aug 2008 04:16:19 -0000 @@ -131,6 +131,7 @@ $string['typeonline'] = 'Online text'; $string['typeupload'] = 'Advanced uploading of files'; $string['typeuploadsingle'] = 'Upload a single file'; +$string['typeblog'] = 'Blog post'; $string['unfinalize'] = 'Revert to draft'; $string['unfinalizeerror'] = 'An error occurred and that submission could not be reverted to draft'; $string['uploadbadname'] = 'This filename contained strange characters and couldn\'t be uploaded'; @@ -145,5 +146,5 @@ $string['viewfeedback'] = 'View assignment grades and feedback'; $string['viewsubmissions'] = 'View $a submitted assignments'; $string['yoursubmission'] = 'Your submission'; - +$string['maxpublishstate'] = 'Maximum visibility for blog entry before duedate'; ?> Index: lang/en_utf8/blog.php =================================================================== RCS file: /cvsroot/moodle/moodle/lang/en_utf8/blog.php,v retrieving revision 1.26 diff -u -a -w -b -B -r1.26 blog.php --- lang/en_utf8/blog.php 24 Jul 2008 04:59:29 -0000 1.26 +++ lang/en_utf8/blog.php 13 Aug 2008 04:16:19 -0000 @@ -67,5 +67,18 @@ $string['viewsiteentries'] = 'View site entries'; $string['wrongpostid'] = 'Wrong blog post id'; $string['worldblogs'] = 'The world can read entries set to be world-accessible'; - +$string['associations'] = 'Associations';$string['publishtocourse'] = 'Users sharing a course with you'; +$string['publishtogroup'] = 'Users sharing a group with you'; +$string['publishtocourseassoc'] = 'Members of the associated course'; +$string['publishtogroupassoc'] = 'Your group members in the associated course'; +$string['associationunviewable'] = 'This entry cannot be viewed by others until a course is associated with it or the \'Publish To\' field is changed'; +$string['mustassociatecourse'] = 'If you are publishing to course or group members, you must associate a course with this entry'; +$string['viewuserentries'] = 'View user entries'; +$string['viewmodentries'] = 'View module entries'; +$string['viewgroupentries'] = 'View group entries'; +$string['viewcourseblogs'] = 'View entries for course...'; +$string['viewmodblogs'] = 'View entries for module...'; +$string['viewgroupblogs'] = 'View entries for group...'; +$string['viewblogsfor'] = 'View all entries for...'; +$string['filterblogsby'] = 'Filter entries by...'; ?> Index: lib/accesslib.php =================================================================== RCS file: /cvsroot/moodle/moodle/lib/accesslib.php,v retrieving revision 1.509 diff -u -a -w -b -B -r1.509 accesslib.php --- lib/accesslib.php 6 Aug 2008 05:07:47 -0000 1.509 +++ lib/accesslib.php 13 Aug 2008 04:16:21 -0000 @@ -2099,7 +2099,8 @@ if ($context = $DB->get_record('context', array('contextlevel'=>$contextlevel, 'instanceid'=>$instanceid))) { $result = $DB->delete_records('role_assignments', array('contextid'=>$context->id)) && $DB->delete_records('role_capabilities', array('contextid'=>$context->id)) && - $DB->delete_records('context', array('id'=>$context->id)); + $DB->delete_records('context', array('id'=>$context->id)) && + $DB->delete_records('blog_association', array('contextid'=>$context->id)); // do not mark dirty contexts if parents unknown if (!is_null($context->path) and $context->depth > 0) { @@ -2779,6 +2780,7 @@ function role_unassign($roleid=0, $userid=0, $groupid=0, $contextid=0, $enrol=NULL) { global $USER, $CFG, $DB; + require_once($CFG->dirroot.'/group/lib.php'); $success = true; Index: lib/db/install.xml =================================================================== RCS file: /cvsroot/moodle/moodle/lib/db/install.xml,v retrieving revision 1.164 diff -u -a -w -b -B -r1.164 install.xml --- lib/db/install.xml 7 Aug 2008 10:17:47 -0000 1.164 +++ lib/db/install.xml 13 Aug 2008 04:16:21 -0000 @@ -4,7 +4,21 @@ xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd" > - +
    + + + + + + + + + + + + +
    + @@ -717,7 +731,7 @@ - + Index: lib/db/upgrade.php =================================================================== RCS file: /cvsroot/moodle/moodle/lib/db/upgrade.php,v retrieving revision 1.226 diff -u -a -w -b -B -r1.226 upgrade.php --- lib/db/upgrade.php 7 Aug 2008 13:36:59 -0000 1.226 +++ lib/db/upgrade.php 13 Aug 2008 04:16:22 -0000 @@ -616,6 +616,34 @@ /// Main savepoint reached upgrade_main_savepoint($result, 2008080701); } + if ($result && $oldversion < 2008081201) { + /// Define table blog_association to be created + $table = new xmldb_table('blog_association'); + + /// Adding fields to table blog_association + $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); + $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); + $table->add_field('blogid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); + /// Adding keys to table blog_association + $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); + $table->add_key('contextid', XMLDB_KEY_FOREIGN, array('contextid'), 'context', array('id')); + $table->add_key('blogid', XMLDB_KEY_FOREIGN, array('blogid'), 'post', array('id')); + + if (!$dbman->table_exists($table)) { + /// Launch create table for blog_association + $dbman->create_table($table); + } + + /// Updating available post states + $table = new xmldb_table('post'); + $field = new xmldb_field('publishstate'); + $dbman->drop_field($table, $field); + $table->add_field('publishstate', XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, XMLDB_ENUM, + array('draft', 'public', 'site', 'group', 'course'), 'public'); + + + /// Main savepoint reached + } return $result; } Index: mod/assignment/lib.php =================================================================== RCS file: /cvsroot/moodle/moodle/mod/assignment/lib.php,v retrieving revision 1.343 diff -u -a -w -b -B -r1.343 lib.php --- mod/assignment/lib.php 9 Aug 2008 14:24:58 -0000 1.343 +++ mod/assignment/lib.php 13 Aug 2008 04:16:23 -0000 @@ -1376,7 +1376,7 @@ * @return object The updated submission object */ function process_feedback() { - global $CFG, $USER; + global $CFG, $USER, $DB; require_once($CFG->libdir.'/gradelib.php'); if (!$feedback = data_submitted()) { // No incoming data? Index: tag/index.php =================================================================== RCS file: /cvsroot/moodle/moodle/tag/index.php,v retrieving revision 1.29 diff -u -a -w -b -B -r1.29 index.php --- tag/index.php 30 Jun 2008 09:04:09 -0000 1.29 +++ tag/index.php 13 Aug 2008 04:16:24 -0000 @@ -103,7 +103,7 @@ if (has_capability('moodle/blog:view', $systemcontext)) { // You have to see blogs obviously $count = 10; - if ($blogs = blog_fetch_entries('', $count, 0, 'site', '', $tag->id)) { + if ($blogs = blog_fetch_entries($count, 0, array('tag'=>$tag->id))) { print_box_start('generalbox', 'tag-blogs'); $heading = get_string('relatedblogs', 'tag', $tagname); @@ -129,7 +129,7 @@ } echo ''; - echo '

    '.get_string('seeallblogs', 'tag', $tagname).'

    '; + echo '

    '.get_string('seeallblogs', 'tag', $tagname).'

    '; print_box_end(); } Index: user/tabs.php =================================================================== RCS file: /cvsroot/moodle/moodle/user/tabs.php,v retrieving revision 1.58 diff -u -a -w -b -B -r1.58 tabs.php --- user/tabs.php 7 Aug 2008 09:01:16 -0000 1.58 +++ user/tabs.php 13 Aug 2008 04:16:24 -0000 @@ -2,6 +2,9 @@ /// This file to be included so we can assume config.php has already been included. /// We also assume that $user, $course, $currenttab have been set + require_once($CFG->dirroot.'/blog/lib.php'); + + if (!isset($filtertype)) { $filtertype = ''; } @@ -39,7 +42,7 @@ get_string('participants')); } - $toprow[] = new tabobject('blogs', $CFG->wwwroot.'/blog/index.php?filtertype=site&', + $toprow[] = new tabobject('blogs', blog_get_blogs_url(array()), get_string('blogs','blog')); } @@ -56,11 +59,11 @@ get_string('participants')); if ($CFG->bloglevel >= 3) { - $toprow[] = new tabobject('blogs', $CFG->wwwroot.'/blog/index.php?filtertype=course&filterselect='.$filterselect, get_string('blogs','blog')); + $toprow[] = new tabobject('blogs', blog_get_blogs_url(array('course'=>$filterselect)), get_string('blogs','blog')); } if (has_capability('moodle/notes:manage', $coursecontext) || has_capability('moodle/notes:view', $coursecontext)) { - $toprow[] = new tabobject('notes', $CFG->wwwroot.'/notes/index.php?filtertype=course&filterselect=' . $filterselect, get_string('notes', 'notes')); + $toprow[] = new tabobject('notes', blog_get_blogs_url(array('course'=>$filterselect)), get_string('notes', 'notes')); } /************************************** @@ -77,7 +80,7 @@ get_string('participants')); - $toprow[] = new tabobject('blogs', $CFG->wwwroot.'/blog/index.php?filtertype=group&filterselect='.$filterselect, get_string('blogs','blog')); + $toprow[] = new tabobject('blogs', blog_get_blogs_url(array('group'=>$filterselect)), get_string('blogs','blog')); } /************************************** @@ -168,7 +171,7 @@ ) // able to read blogs in site or course context ) { //end if - $toprow[] = new tabobject('blogs', $CFG->wwwroot.'/blog/index.php?userid='.$user->id.'&courseid='.$course->id, get_string('blog', 'blog')); + $toprow[] = new tabobject('blogs', blog_get_blogs_url(array('user'=>$user->id,'course'=>$course->id)), get_string('blog', 'blog')); } if (has_capability('moodle/notes:manage', $coursecontext) || has_capability('moodle/notes:view', $coursecontext)) { Index: mod/assignment/type/blog/assignment.class.php =================================================================== RCS file: mod/assignment/type/blog/assignment.class.php diff -N mod/assignment/type/blog/assignment.class.php --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ mod/assignment/type/blog/assignment.class.php 11 Aug 2008 09:11:15 -0000 @@ -0,0 +1,313 @@ +dirroot .'/blog/lib.php'); +require_once($CFG->libdir.'/formslib.php'); + + +/** + * Extend the base assignment class for offline assignments + * + */ +class assignment_blog extends assignment_base { + + function assignment_blog($cmid='staticonly', $assignment=NULL, $cm=NULL, $course=NULL) { + parent::assignment_base($cmid, $assignment, $cm, $course); + $this->type = 'blog'; + } + + function display_lateness($timesubmitted) { + return ''; + } + + function print_student_answer($userid, $return=false){ + global $CFG, $DB; + if (!$submission = $this->get_submission($userid)) { + return ''; + } + $post = $DB->get_record('post', array('id' => $submission->data1)); + $ret = ''.$post->subject.':
    '.shorten_text(format_text($post->summary)); + $ret .= 'Full Entry
    '; + + return $ret; + } + + + function setup_elements(&$mform) { + $ynoptions = array( 0 => get_string('no'), 1 => get_string('yes')); + //$mform->addElement('select', 'var1', get_string('multiassoc', 'assignment'), $ynoptions); + //$mform->setHelpButton('var1', array('multiassoc', get_string('multiassoc', 'assignment'), 'assignment')); + //$mform->setDefault('var1', 0); + + $publishstates = array(); + $i = 0; + foreach(blog_applicable_publish_states() as $state) $publishstates[$i++] = $state; + $mform->addElement('select', 'var2', get_string('maxpublishstate', 'assignment'), $publishstates); + $mform->setDefault('var2', 0); + } + + function prepare_new_submission($userid) { + $submission = new Object; + $submission->assignment = $this->assignment->id; + $submission->userid = $userid; + $submission->timecreated = time(); // needed for offline assignments + $submission->timemodified = $submission->timecreated; + $submission->numfiles = 0; + $submission->data1 = ''; + $submission->data2 = ''; + $submission->grade = -1; + $submission->submissioncomment = ''; + $submission->format = 0; + $submission->teacher = 0; + $submission->timemarked = 0; + $submission->mailed = 0; + return $submission; + } + + // needed for the timemodified override + function process_feedback() { + global $CFG, $USER, $DB; + require_once($CFG->libdir.'/gradelib.php'); + + if (!$feedback = data_submitted()) { // No incoming data? + return false; + } + + ///For save and next, we need to know the userid to save, and the userid to go + ///We use a new hidden field in the form, and set it to -1. If it's set, we use this + ///as the userid to store + if ((int)$feedback->saveuserid !== -1){ + $feedback->userid = $feedback->saveuserid; + } + + if (!empty($feedback->cancel)) { // User hit cancel button + return false; + } + + $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, $feedback->userid); + + // store outcomes if needed + $this->process_outcomes($feedback->userid); + + $submission = $this->get_submission($feedback->userid, true); // Get or make one + + if (!$grading_info->items[0]->grades[$feedback->userid]->locked and + !$grading_info->items[0]->grades[$feedback->userid]->overridden) { + + $submission->grade = $feedback->grade; + $submission->submissioncomment = $feedback->submissioncomment; + $submission->format = $feedback->format; + $submission->teacher = $USER->id; + $mailinfo = get_user_preferences('assignment_mailinfo', 0); + if (!$mailinfo) { + $submission->mailed = 1; // treat as already mailed + } else { + $submission->mailed = 0; // Make sure mail goes out (again, even) + } + $submission->timemarked = time(); + + unset($submission->data1); // Don't need to update this. + unset($submission->data2); // Don't need to update this. + + if (empty($submission->timemodified)) { // eg for offline assignments + $submission->timemodified = time(); + } + + if (! $DB->update_record('assignment_submissions', $submission)) { + return false; + } + + // triger grade event + $this->update_grade($submission); + + add_to_log($this->course->id, 'assignment', 'update grades', + 'submissions.php?id='.$this->assignment->id.'&user='.$feedback->userid, $feedback->userid, $this->cm->id); + } + + return $submission; + + } + + + function view() { + + global $USER, $DB; + + $edit = optional_param('edit', 0, PARAM_BOOL); + $saved = optional_param('saved', 0, PARAM_BOOL); + + $context = get_context_instance(CONTEXT_MODULE, $this->cm->id); + require_capability('mod/assignment:view', $context); + + $submission = $this->get_submission(); + + //Guest can not submit nor edit an assignment (bug: 4604) + if (!has_capability('mod/assignment:submit', $context)) { + $editable = null; + } else { + $editable = $this->isopen(); + } + $editmode = ($editable and $edit); + + if ($editmode) { + //guest can not edit or submit assignment + if (!has_capability('mod/assignment:submit', $context)) { + print_error('guestnosubmit', 'assignment'); + } + } + + add_to_log($this->course->id, "assignment", "view", "view.php?id={$this->cm->id}", $this->assignment->id, $this->cm->id); + +/// prepare form and process submitted data + $mform = new mod_assignment_blog_edit_form(); + if($this->assignment->var1) { //allow multiple associations + $mform->set_multiple_assoc(); + } + + $defaults = new object(); + if($submission = $this->get_submission()) + $defaults->selectblog = $submission->data1; + $defaults->id = $this->cm->id; + + $mform->set_data($defaults); + + if ($mform->is_cancelled()) { + redirect('view.php?id='.$this->cm->id); + } + + if ($data = $mform->get_data()) { // No incoming data? + if ($editable && $this->update_submission($data)) { + //TODO fix log actions - needs db upgrade + $submission = $this->get_submission(); + add_to_log($this->course->id, 'assignment', 'upload', + 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id); + $this->email_teachers($submission); + //redirect to get updated submission date and word count + redirect('view.php?id='.$this->cm->id.'&saved=1'); + } else { + // TODO: add better error message + notify(get_string("error")); //submitting not allowed! + } + } + +/// print header, etc. and display form if needed + if ($editmode) { + $this->view_header(get_string('editmysubmission', 'assignment')); + } else { + $this->view_header(); + } + + $this->view_intro(); + + $this->view_dates(); + + if ($saved) { + notify(get_string('submissionsaved', 'assignment'), 'notifysuccess'); + } + + if (has_capability('mod/assignment:submit', $context)) { + print_simple_box_start('center', '70%', '', 0, 'generalbox', 'online'); + if ($editmode) { + $mform->display(); + } else { + if ($submission) { + blog_print_entry($DB->get_record('post', array('id' => $submission->data1))); + } else if (!has_capability('mod/assignment:submit', $context)) { //fix for #4604 + echo '
    '. get_string('guestnosubmit', 'assignment').'
    '; + } else if ($this->isopen()){ //fix for #4206 + echo '
    '.get_string('emptysubmission', 'assignment').'
    '; + } + } + print_simple_box_end(); + if (!$editmode && $editable) { + echo "
    "; + print_single_button('view.php', array('id'=>$this->cm->id,'edit'=>'1'), + get_string('editmysubmission', 'assignment')); + echo "
    "; + } + + } + + $this->view_feedback(); + + $this->view_footer(); + } + + + function update_submission($data) { + global $CFG, $USER, $DB, $COURSE; + + $submission = $this->get_submission($USER->id, true); + + $update = new object(); + $update->id = $submission->id; + $update->data1 = $data->selectblog; + $update->timemodified = time(); + + //enforce access restriction + $postaccess = -1; + $i=0; + $post = $DB->get_record('post', array('id' => $data->selectblog)); + if(!$post) { + print_error('blognotfound', 'blog'); + } + $publishstates = array(); + foreach(blog_applicable_publish_states() as $state => $desc) { + if($state == $post->publishstate) + $postaccess = $i; + $publishstates[$i++] = $state; + } + + if($this->assignment->var2 < $postaccess) { + $post->publishstate = $publishstates[$this->assignment->var2]; + $DB->update_record('post', $post); + } + + //force the user to have strict associations with this post + blog_remove_associations($post->id); + $assignmentmodid = $DB->get_field('modules', 'id', array('name' => 'assignment')); + $modcontext = get_context_instance(CONTEXT_MODULE, $DB->get_field('course_modules', 'id', + array('module' => $assignmentmodid, 'instance' => $this->assignment->id))); + blog_add_association($post->id, $modcontext->id); + + if (!$DB->update_record('assignment_submissions', $update)) { + return false; + } + + $submission = $this->get_submission($USER->id); + $this->update_grade($submission); + return true; + } + + +} + +class mod_assignment_blog_edit_form extends moodleform { + function definition() { + global $USER, $DB; + $mform =& $this->_form; + + // visible elements + //$mform->addRule('text', get_string('required'), 'required', null, 'client'); + + $blogentries = array(); + foreach($DB->get_records('post', array('userid' => $USER->id)) as $rec) { + $blogentries[$rec->id] = userdate($rec->created) . ' - ' . $rec->summary; + } + + $mform->addElement('select', 'selectblog', get_string('selectblog', 'assignment'), $blogentries); + + // hidden params + $mform->addElement('hidden', 'id', 0); + $mform->setType('id', PARAM_INT); + + // buttons + $this->add_action_buttons(); + } + + function set_multiple_assoc() { + $mform =& $this->_form; + $selectblog = $mform->getElement('selectblog'); + $selectblog->setMultiple(true); + } +} + +?>